from docx import Document
from docx.shared import Inches, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_LINE_SPACING
from docx.oxml.ns import qn
from docx.oxml import OxmlElement


class ApiDocGenerator:
    """接口文档生成工具类"""

    def __init__(self, title: str, save_path: str = "api_document.docx"):
        """
        初始化文档生成器
        :param title: 文档标题
        :param save_path: 保存路径
        """
        self.doc = Document()
        self.save_path = save_path
        self._set_document_style()  # 设置全局样式
        self.add_title(title)  # 添加标题

    def _set_document_style(self):
        """设置文档全局样式（字体、间距等）"""
        # 设置默认字体为宋体（支持中文）
        for style in self.doc.styles:
            if style.name in ["Normal", "Heading 1", "Heading 2", "Heading 3", "Code"]:
                style.font.name = "宋体"
                style.element.rPr.rFonts.set(qn('w:eastAsia'), "宋体")  # 解决中文显示问题

        # 设置标题样式
        self.doc.styles["Heading 1"].font.size = Pt(16)
        self.doc.styles["Heading 1"].font.bold = True
        self.doc.styles["Heading 1"].paragraph_format.space_after = Pt(12)

        self.doc.styles["Heading 2"].font.size = Pt(14)
        self.doc.styles["Heading 2"].font.bold = True
        self.doc.styles["Heading 2"].paragraph_format.space_after = Pt(10)

        self.doc.styles["Heading 3"].font.size = Pt(12)
        self.doc.styles["Heading 3"].font.bold = True
        self.doc.styles["Heading 3"].paragraph_format.space_after = Pt(8)

        # 设置正文样式
        self.doc.styles["Normal"].font.size = Pt(10.5)
        self.doc.styles["Normal"].paragraph_format.line_spacing_rule = WD_LINE_SPACING.ONE_POINT_FIVE  # 1.5倍行距
        self.doc.styles["Normal"].paragraph_format.space_after = Pt(5)

        # 添加代码块样式（修改为正确设置背景色的方式）
        code_style = self.doc.styles.add_style("Code", 1)
        code_style.base_style = self.doc.styles["Normal"]
        code_style.font.name = "Consolas"
        code_style.element.rPr.rFonts.set(qn('w:eastAsia'), "Consolas")  # 代码使用等宽字体
        code_style.font.size = Pt(9)

    def add_title(self, text: str):
        """添加文档主标题"""
        title = self.doc.add_heading(text, level=0)
        title.alignment = WD_ALIGN_PARAGRAPH.CENTER  # 居中对齐
        title.paragraph_format.space_after = Pt(20)

    def add_heading(self, text: str, level: int = 1):
        """添加层级标题（1-3级）"""
        if level not in [1, 2, 3]:
            raise ValueError("标题级别仅支持1-3级")
        self.doc.add_heading(text, level=level)

    def add_paragraph(self, text: str, bold: bool = False, color: RGBColor = None, add_shading: bool = False):
        """添加段落文本"""
        para = self.doc.add_paragraph()
        run = para.add_run(text)
        if bold:
            run.bold = True
        if color:
            run.font.color.rgb = color
            
        # 如果需要添加背景色（用于代码块）
        if add_shading:
            self._add_paragraph_shading(para, RGBColor(240, 240, 240))
            
        return para

    def _add_paragraph_shading(self, paragraph, color):
        """为段落添加背景色（修复后的方法）"""
        # 获取段落的XML元素
        p = paragraph._element
        
        # 创建w:shd元素并设置属性
        shd = OxmlElement('w:shd')
        shd.set(qn('w:fill'), '%02X%02X%02X' % (color.r, color.g, color.b))
        
        # 将w:shd元素添加到段落的rPr（运行属性）中
        pPr = p.get_or_add_pPr()
        pPr.append(shd)

    def add_table(self, headers: list, data: list, width: float = 6.0):
        """
        添加表格
        :param headers: 表头列表（如 ["参数名", "类型"]）
        :param data: 数据列表（二维列表，如 [["name", "string"], ...]）
        :param width: 表格总宽度（英寸）
        """
        cols = len(headers)
        table = self.doc.add_table(rows=1, cols=cols)
        table.autofit = False  # 关闭自动适应，手动设置宽度

        # 设置表头
        hdr_cells = table.rows[0].cells
        for i, header in enumerate(headers):
            hdr_cells[i].text = header
            hdr_cells[i].paragraphs[0].runs[0].bold = True  # 表头加粗

        # 添加数据行
        for row_data in data:
            row_cells = table.add_row().cells
            for i, cell_text in enumerate(row_data):
                row_cells[i].text = str(cell_text)  # 确保文本类型

        # 平均分配列宽
        col_width = Inches(width / cols)
        for col in table.columns:
            for cell in col.cells:
                cell.width = col_width

    def add_code_block(self, code: str, language: str = "json"):
        """添加代码块（带灰色背景）"""
        self.doc.add_paragraph(f"{language} 代码示例：", style="Normal")
        para = self.doc.add_paragraph(code, style="Code")
        para.paragraph_format.left_indent = Inches(0.3)  # 缩进
        
        # 添加背景色
        self._add_paragraph_shading(para, RGBColor(240, 240, 240))

    def add_page_break(self):
        """添加分页符"""
        self.doc.add_page_break()

    def save(self):
        """保存文档"""
        self.doc.save(self.save_path)
        print(f"文档已保存至：{self.save_path}")


# ------------------------------
# 使用示例（生成培训数据接口文档）
# ------------------------------
if __name__ == "__main__":
    # 初始化文档生成器
    doc = ApiDocGenerator(
        title="培训数据回传接口文档",
        save_path="培训数据接口文档.docx"
    )

    # 1. 添加概述
    doc.add_heading("一、接口概述", level=1)
    doc.add_paragraph("本接口用于处理各类培训数据的提交和同步请求，支持国家培训数据、课程考试数据等多种类型的回传。")
    doc.add_table(
        headers=["基础信息", "说明"],
        data=[
            ["接口版本", "v1.0"],
            ["基础路径", "/api/training/data"],
            ["请求方式", "POST"],
            ["数据格式", "JSON"],
            ["签名验证", "需AK/SK签名"]
        ]
    )

    # 2. 通用请求参数
    doc.add_heading("二、通用请求参数", level=1)
    doc.add_heading("2.1 请求头（Headers）", level=2)
    doc.add_table(
        headers=["参数名", "类型", "必选", "描述"],
        data=[
            ["Content-Type", "String", "是", "application/json"],
            ["X-Date", "String", "是", "UTC时间戳（如2024-07-15T12:00:00Z）"],
            ["Authorization", "String", "是", "签名信息"]
        ]
    )

    # 3. 具体接口示例（回传国家培训数据）
    doc.add_heading("三、具体接口详情", level=1)
    doc.add_heading("3.1 回传国家培训数据", level=2)
    doc.add_paragraph("接口地址：/country", bold=True)
    doc.add_paragraph("接口描述：获取各国家/地区的培训数据统计，包括培训次数、参与人数等指标。")

    doc.add_heading("请求示例", level=3)
    doc.add_code_block("""{
  "startTime": "2024-01-01 00:00:00",
  "endTime": "2024-06-30 23:59:59",
  "pageNum": 1,
  "pageSize": 20
}""")

    doc.add_heading("响应示例", level=3)
    doc.add_code_block("""{
  "code": 0,
  "message": "success",
  "data": [
    {
      "countryCode": "CN",
      "countryName": "中国",
      "trainingCount": 1560,
      "participantNum": 28900
    }
  ]
}""")

    # 4. 错误码说明
    doc.add_heading("四、错误码说明", level=1)
    doc.add_table(
        headers=["错误码", "描述", "解决方案"],
        data=[
            ["0", "成功", "-"],
            ["401", "签名验证失败", "检查AK/SK及签名逻辑"],
            ["500", "服务器错误", "联系技术支持"]
        ]
    )

    # 保存文档
    doc.save()